package controller;

import java.util.Calendar;

import utils.Utils;
import android.content.Context;
import android.util.Log;
import app.fitness.fragment.DashBoardDetailFragment;
import app.fitness.fragment.DashBoardFragment;

import com.razer.android.nabuopensdk.NabuOpenSDK;
import com.razer.android.nabuopensdk.interfaces.FitnessHistoryListener;
import com.razer.android.nabuopensdk.interfaces.FitnessListener;
import com.razer.android.nabuopensdk.models.NabuFitness;
import com.razer.android.nabuopensdk.models.NabuFitnessHistory;
import com.razerzone.android.fitness.R;

import define.Constants;
import define.FitnessData;
import define.FitnessHistoryData;
import define.Key;
import define.TimeLine;

public class GetFitnessData {

	/**
	 * String section
	 */
	private int KEY = Key.FITNESS_HISTORY_DATA;

	private int SUM_CALORIES = 0;
	private float SUM_DISTANCE = 0;
	private int SUM_STEPS = 0;

	/**
	 * View section
	 */

	/**
	 * The other section
	 */
	private static Context context;

	public GetFitnessData(Context context) {
		GetFitnessData.context = context;
	}

	private void addDataToArray(NabuFitness[] nabuFitness,
			NabuFitnessHistory[] nabuFitnessHistory) {
		/**
		 * Received the record time in GMT type Add data : Steps, calories,
		 * distance also
		 */
		switch (KEY) {
		case Key.FITNESS_DATA:
			int length = 0;
			if (FitnessData.DAILY_STEPS.length < nabuFitness.length) {
				length = FitnessData.DAILY_STEPS.length;
			} else {
				length = nabuFitness.length;
			}

			int index = 0;
			for (NabuFitness data : nabuFitness) {
				if (index < length) {
					TimeLine.mLlFhdTimeLineDailyLocal.add(data.recordTime);

					FitnessData.DAILY_CALORIES[index] = data.fitness.calories;
					FitnessData.DAILY_DISTANCE[index] = (float) data.fitness.distanceWalked / 1000;
					FitnessData.DAILY_STEPS[index] = data.fitness.steps;

					index++;
				} else if (index == length) {
					break;
				} else {
					index++;
					continue;
				}
			}

			index = 0;
			for (NabuFitness data : nabuFitness) {
				if (index < length) {
					/**
					 * Convert to local time
					 */
					Calendar mCalendar = Calendar.getInstance();
					mCalendar.setTimeInMillis(data.recordTime * 1000);

					/**
					 * Object
					 */
					model.FitnessData fitnessData = new model.FitnessData(
							mCalendar.getTime(), data.fitness.calories + "",
							(float) data.fitness.distanceWalked / 1000 + "",
							data.fitness.steps + "");

					/**
					 * Store popular data in here : Local Date, Calories,
					 * Distance, Steps
					 */
					FitnessData.mLlFitnessData.add(fitnessData);

					index++;
				} else if (index == length) {
					break;
				} else {
					index++;
					continue;
				}
			}
			break;
		case Key.FITNESS_HISTORY_DATA:
			if (nabuFitnessHistory.length == 0) {
				return;
			}

			// First Day has valid data
			Calendar mCalendarFirstDateHasValidData = Calendar.getInstance();
			mCalendarFirstDateHasValidData
					.setTimeInMillis(nabuFitnessHistory[0].recordDate * 1000);

			int days = (int) ((Calendar.getInstance().getTimeInMillis() - mCalendarFirstDateHasValidData
					.getTimeInMillis()) / 86400000);

			// Log.i("", "days " + days);

			// Offset
			int offset_from_today = 0;
			while (offset_from_today < days) {
				model.FitnessData fitnessHistoryData = new model.FitnessData(
						null, "0", "0", "0");
				FitnessHistoryData.fitness_history_data[offset_from_today] = fitnessHistoryData;

				offset_from_today++;
			}

			// Offset
			for (int i = 0; i < nabuFitnessHistory.length; i++) {
				/**
				 * Convert to local time
				 */
				// Day has valid data
				Calendar mCalendarDateHasValidData = Calendar.getInstance();
				mCalendarDateHasValidData
						.setTimeInMillis(nabuFitnessHistory[i].recordDate * 1000);

				/**
				 * Object
				 */
				model.FitnessData fitnessHistoryData = new model.FitnessData(
						mCalendarDateHasValidData.getTime(),
						nabuFitnessHistory[i].fitness.calories + "",
						(float) nabuFitnessHistory[i].fitness.distanceWalked
								/ 1000 + "",
						nabuFitnessHistory[i].fitness.steps + "");

				FitnessHistoryData.fitness_history_data[offset_from_today] = fitnessHistoryData;

				// Log.i("", "FITNESS - offset " + offset_from_today + " " +
				// Utils.showDate(mCalendarDateHasValidData.getTime()) +
				// " steps - " +
				// FitnessHistoryData.fitness_history_data[offset_from_today]
				// .getStepsCurrent());

				/**
				 * Some days don't have data, so should set them be null, and
				 * skip them also
				 */
				if ((i + 1) == nabuFitnessHistory.length) {
					break;
				} else {
					Calendar mCalendarDateHasValidDataBefore = Calendar
							.getInstance();
					mCalendarDateHasValidDataBefore
							.setTimeInMillis(nabuFitnessHistory[i + 1].recordDate * 1000);

					/**
					 * Should calculate offset correct equal to index in array
					 */
					if (mCalendarDateHasValidDataBefore.get(Calendar.MONTH) == mCalendarDateHasValidData
							.get(Calendar.MONTH)) {
						offset_from_today += (mCalendarDateHasValidData
								.get(Calendar.DAY_OF_MONTH) - mCalendarDateHasValidDataBefore
								.get(Calendar.DAY_OF_MONTH));
					} else if (mCalendarDateHasValidDataBefore
							.get(Calendar.MONTH) < mCalendarDateHasValidData
							.get(Calendar.MONTH)) {
						long day_in_milliseconds = mCalendarDateHasValidData
								.getTimeInMillis()
								- mCalendarDateHasValidDataBefore
										.getTimeInMillis();

						int day = (int) day_in_milliseconds / 86400000;

						offset_from_today += day;
					}
				}
			}
			break;
		default:
			break;
		}
	}

	public static void clearOldData() {
		TimeLine.mLlFhdTimeLineDailyGMT.clear();
		TimeLine.mLlFhdTimeLineDailyLocal.clear();

		for (int i = 0; i < define.FitnessData.DAILY_CALORIES.length; i++) {
			FitnessData.DAILY_CALORIES[i] = 0;
		}
		for (int i = 0; i < define.FitnessData.DAILY_DISTANCE.length; i++) {
			FitnessData.DAILY_DISTANCE[i] = 0;
		}
		for (int i = 0; i < define.FitnessData.DAILY_STEPS.length; i++) {
			FitnessData.DAILY_STEPS[i] = 0;
		}
	}

	public void getData(Integer... params) {
		KEY = params[0];

		/**
		 * Fitness Data
		 */
		if (Constants.nabuSDK == null) {
			Constants.nabuSDK = NabuOpenSDK.getInstance(context);
		}

		/**
		 * Check parameter is to get Fitness data | Fitness history data
		 */
		switch (KEY) {
		case Key.FITNESS_DATA:
			getFitnessData(params[1]);
			break;
		case Key.FITNESS_HISTORY_DATA:
			getFitnessHistoryData(params[1]);
			break;
		default:
			break;
		}
	}

	private void getFitnessData(final int recordTime) {
		Constants.nabuSDK.getFitnessData(context, recordTime,
				new FitnessListener() {

					@Override
					public void onReceiveData(NabuFitness[] data) {
						Log.i("", "getFitnessData - data.length " + data.length);

						/**
						 * Step 2 : Put data into array to store
						 */
						KEY = Key.FITNESS_DATA;
						addDataToArray(data, null);

						/**
						 * Set up data
						 */
						setDataToShowOnPage(data.length);

						/**
						 * Can not pass null Step 3 : Update data on the view
						 */
						updateDataOnPage();

						// Log.i("", "getFitnessData is done");

						/**
						 * Dismiss progress dialog after already download
						 * array[365]
						 */
						if (DashBoardFragment.IS_AUTHENTICATE) {
							DashBoardFragment.IS_AUTHENTICATE = false;

							if (DashBoardFragment.iTaskCallBacks != null) {
								DashBoardFragment.iTaskCallBacks
										.onCompleteReceiveData();
							}
						}

						if (DashBoardFragment.iTaskCallBacks != null) {
							DashBoardFragment.iTaskCallBacks
									.onCompleteReceiveData();
						}
					}

					@Override
					public void onReceiveFailed(String error) {
						Log.i("", "getFitnessData - onReceiveFailed " + error);

						/**
						 * If get invalid token, need terminate the application
						 */
						if (error.equals(Constants.INVALID_TOKEN)) {
							/**
							 * Deleted cache before exit
							 */
							Utils.clearApplicationData(context);

							try {
								Thread.sleep(2000);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}

							android.os.Process.killProcess(android.os.Process
									.myPid());
						}
					}
				});
	}

	private void getFitnessHistoryData(int number_of_days) {
		Constants.nabuSDK.getFitnessHistoryData(context, number_of_days,
				new FitnessHistoryListener() {

					@Override
					public void onReceiveData(NabuFitnessHistory[] data) {
						Log.i("", "getFitnessHistoryData - data.length "
								+ data.length);

						/**
						 * Step 2 : Put data into array to store
						 */
						KEY = Key.FITNESS_HISTORY_DATA;
						addDataToArray(null, data);

						// Log.i("", "getFitnessHistoryData is done");
					}

					@Override
					public void onReceiveFailed(String error) {
						Log.i("", "getFitnessHistoryData - onReceiveFailed "
								+ error);

						// android.os.Process.killProcess(android.os.Process
						// .myPid());
					}
				});
	}

	private void saveDataIntoSingleTon() {
		switch (KEY) {
		case Key.FITNESS_DATA:
			SUM_CALORIES = 0;
			for (int calories : FitnessData.DAILY_CALORIES) {
				SUM_CALORIES += calories;
			}

			SUM_DISTANCE = 0;
			for (float distance : FitnessData.DAILY_DISTANCE) {
				SUM_DISTANCE += distance;
			}

			SUM_STEPS = 0;
			for (int steps : FitnessData.DAILY_STEPS) {
				SUM_STEPS += steps;
			}

			// Save into single ton current value
			DashBoardFragment.singleTon.setCaloriesCurrent(SUM_CALORIES + "");
			DashBoardFragment.singleTon.setDistanceCurrent(SUM_DISTANCE + "");
			DashBoardFragment.singleTon.setStepsCurrent(SUM_STEPS + "");

			/**
			 * Save into specify single ton to sum data for the others since
			 * this data always change
			 */
			/**
			 * Should check one time Need check current day is today or not, if
			 * not, should set all values in today is 0
			 */
			if (DashBoardFragment.IS_FIRST_TIME_DOWNLOAD_DATA_TODAY_FITNESS) {
				DashBoardFragment.IS_FIRST_TIME_DOWNLOAD_DATA_TODAY_FITNESS = false;
				if (DashBoardFragment.singleTon.getCurrentDate().contains(
						context.getString(R.string.today))) {
					DashBoardFragment.singleTon.setCaloriesToday(SUM_CALORIES
							+ "");
					DashBoardFragment.singleTon.setDistanceToday(SUM_DISTANCE
							+ "");
					DashBoardFragment.singleTon.setStepsToday(SUM_STEPS + "");
				} else {
					DashBoardFragment.singleTon.setCaloriesToday("0");
					DashBoardFragment.singleTon.setDistanceToday("0");
					DashBoardFragment.singleTon.setStepsToday("0");
				}
			}
			break;
		case Key.FITNESS_HISTORY_DATA:
			break;
		default:
			break;
		}
	}

	private void setDataToShowOnPage(int dataLength) {
		switch (KEY) {
		case Key.FITNESS_DATA:
			saveDataIntoSingleTon();
			break;
		case Key.FITNESS_HISTORY_DATA:
			break;
		default:
			break;
		}
	}

	private void updateDataOnPage() {
		if (DashBoardFragment.IS_IN_DASHBOARD) {
			DashBoardFragment.updateFitnessDataOnPage(context,
					DashBoardFragment.singleTon.getCaloriesCurrent(),
					DashBoardFragment.singleTon.getCaloriesGoalDefault(),
					DashBoardFragment.singleTon.getDistanceCurrent(),
					DashBoardFragment.singleTon.getDistanceGoalDefault(),
					DashBoardFragment.singleTon.getStepsCurrent(),
					DashBoardFragment.singleTon.getStepsGoalDefault());
		} else if (DashBoardDetailFragment.IS_IN_DASHBOARD_DETAIL) {
			DashBoardDetailFragment.updateFitnessDataOnPage(context,
					DashBoardFragment.singleTon.getCaloriesCurrent(),
					DashBoardFragment.singleTon.getCaloriesGoalDefault(),
					DashBoardFragment.singleTon.getDistanceCurrent(),
					DashBoardFragment.singleTon.getDistanceGoalDefault(),
					DashBoardFragment.singleTon.getStepsCurrent(),
					DashBoardFragment.singleTon.getStepsGoalDefault());
		}
	}
}
